package respository

import (
	myerror "CodeCover/internal/errors"
	"CodeCover/internal/models"
	"context"
	"errors"
	"fmt"

	"gorm.io/gorm"
)

type MysqlTaskRepository struct {
	db *gorm.DB
}

func NewMysqlTaskRepository(db *gorm.DB) *MysqlTaskRepository {
	db.AutoMigrate(&models.Task{})
	return &MysqlTaskRepository{db: db}
}

// 产生一条新的任务记录
func (r *MysqlTaskRepository) Create(ctx context.Context, task *models.Task) error {
	if ret := r.db.WithContext(ctx).Create(task); ret.Error != nil {
		var code myerror.ErrorCode = myerror.DefaultFailure

		if errors.Is(ret.Error, gorm.ErrForeignKeyViolated) {
			code = myerror.ForeignKeyViolated
		}
		return &myerror.CustomError{
			Code:        code,
			Message:     "MysqlTaskRepository:Create() failed," + ret.Error.Error(),
			OriginError: ret.Error,
			Metadata: map[string]any{
				"task": task,
			},
		}

	}
	return nil

}

func (r *MysqlTaskRepository) FindAllByName(ctx context.Context, username string, page int, pageSize int, start string, end string) ([]models.Task, error) {
	var tasks []models.Task

	conditions := []interface{}{}
	queryStr := "1 = 1"
	if username != "" {
		queryStr += " AND user_name = ?"
		conditions = append(conditions, username)
	}
	if start != "" {
		queryStr += " AND created_at >= ?"
		conditions = append(conditions, start)
	}
	if end != "" {
		queryStr += " AND created_at <= ?"
		conditions = append(conditions, end)
	}
	fmt.Printf("start:%s", start)
	fmt.Printf("end:%s", end)

	offset := (page - 1) * pageSize

	if ret := r.db.WithContext(ctx).Where(queryStr, conditions...).Order("created_at desc").Limit(pageSize).Offset(offset).Find(&tasks); ret.Error != nil {
		return tasks, &myerror.CustomError{
			Code:        myerror.DefaultFailure,
			Message:     "MysqlTaskRepository:FindAllByName() failed," + ret.Error.Error(),
			OriginError: ret.Error,
			Metadata: map[string]any{
				"username": username,
			},
		}
	}
	fmt.Printf("%#v", len(tasks))
	return tasks, nil
}
func (r *MysqlTaskRepository) UpdatePathByTid(ctx context.Context, tid, absPath string) error {

	if ret := r.db.WithContext(ctx).Model(&models.Task{}).Where("tid = ?", tid).Update("abs_path", absPath); ret.Error != nil {
		return &myerror.CustomError{
			Code:        myerror.DefaultFailure,
			Message:     "MysqlTaskRepository:UpdatePathByTid() failed," + ret.Error.Error(),
			OriginError: ret.Error,
			Metadata: map[string]any{
				"tid":     tid,
				"absPath": absPath,
			},
		}
	}
	return nil
}

// GetByTid(ctx context.Context, tid string) models.Task
func (r *MysqlTaskRepository) GetByTid(ctx context.Context, tid string) (*models.Task, error) {
	task := &models.Task{}
	if ret := r.db.WithContext(ctx).Where("tid = ?", tid).Take(&task); ret.Error != nil {
		var code myerror.ErrorCode = myerror.DefaultFailure
		if errors.Is(ret.Error, gorm.ErrRecordNotFound) {
			code = myerror.RecordNotFound
		}
		return nil, &myerror.CustomError{
			Code:        code,
			Message:     "MysqlTaskRepository:GetByTid() failed," + ret.Error.Error(),
			OriginError: ret.Error,
			Metadata: map[string]any{
				"tid": tid,
			},
		}
	}
	return task, nil
}

func (r *MysqlTaskRepository) UpdatePercentById(ctx context.Context, tid string, total int, covered int, percent float64) error {
	ret := r.db.WithContext(ctx).Model(&models.Task{}).Where("tid = ?", tid).Updates(map[string]interface{}{
		"total":   total,
		"covered": covered,
		"percent": percent,
	})
	if ret.Error != nil {
		return &myerror.CustomError{
			Code:        myerror.DefaultFailure,
			Message:     "MysqlTaskRepository:UpdatePercentById() failed," + ret.Error.Error(),
			OriginError: ret.Error,
			Metadata: map[string]any{
				"tid": tid,
			},
		}
	}
	return nil
}
